use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
use std::fmt::{Display, Formatter};

#[derive(
    Serialize_repr,
    Deserialize_repr,
    num_enum::TryFromPrimitive,
    num_enum::IntoPrimitive,
    Debug,
    Clone,
    Eq,
    PartialEq,
)]
#[repr(u32)]
pub enum NetworkAclRuleProtocol {
    Tcp = 1,
    Udp = 2,
    Icmp = 3,
    IcmpV6 = 4,
}

impl NetworkAclRuleProtocol {
    pub fn as_u32(&self) -> u32 {
        self.clone().into()
    }
}

impl Display for NetworkAclRuleProtocol {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        let v: u32 = self.as_u32();
        u32::fmt(&v, f)
    }
}

#[derive(
    Serialize_repr,
    Deserialize_repr,
    num_enum::TryFromPrimitive,
    num_enum::IntoPrimitive,
    Debug,
    Clone,
    Eq,
    PartialEq,
)]
#[repr(u32)]
pub enum NetworkAclRuleDirection {
    Ingress = 1,
    Egress = 2,
}

impl NetworkAclRuleDirection {
    pub fn as_u32(&self) -> u32 {
        self.clone().into()
    }
}

impl Display for NetworkAclRuleDirection {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        let v: u32 = self.as_u32();
        u32::fmt(&v, f)
    }
}

#[derive(
    Serialize_repr,
    Deserialize_repr,
    num_enum::TryFromPrimitive,
    num_enum::IntoPrimitive,
    Debug,
    Clone,
    Eq,
    PartialEq,
)]
#[repr(u32)]
pub enum NetworkAclRuleAction {
    Allow = 1,
    Deny = 2,
}

impl NetworkAclRuleAction {
    pub fn as_u32(&self) -> u32 {
        self.clone().into()
    }
}

impl Display for NetworkAclRuleAction {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        let v: u32 = self.as_u32();
        u32::fmt(&v, f)
    }
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct NetworkAclRule {
    pub description: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub protocol: Option<NetworkAclRuleProtocol>,
    pub action: NetworkAclRuleAction,
    pub src_ip_address: cidr::IpInet,
    pub dst_ip_address: cidr::IpInet,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct NetworkAclRuleItem {
    pub network_acl_rule_id: String,
    #[serde(flatten)]
    pub inner: NetworkAclRule,
}